<html>
<head>
<style type="text/css">
body, td, div, span, p {
	font-family:arial, sans-serif;
}
a {
	color:#0000cc;
}
a:visited {
	color:#551a8b;
}
a:active {
	color:#ff0000;
}
body {
	margin: 0px;
	padding: 0px;
	background-color:white;
}

#EYES_pupil1, #EYES_pupil2 {
	position:relative;
	width:15px;
	height:15px;
	left:52px;
	top:52px;
}
</style>
<title>jQuery-style google eyes</title>
</head>
<body>
<table align="center"  border="0" cellpadding="0" cellspacing="0" style="margin-top: 100px;">
<tbody><tr>
  <td background="./eye_files/eye-r.gif">
   <div style="width:117px;height:117px;">
    <img id="EYES_pupil1" src="./eye_files/pupil.gif" >
   </div>
  </td>
  <td background="./eye_files/eye-y.gif">
   <div style="width:117px;height:117px;">
    <img id="EYES_pupil2" src="./eye_files/pupil.gif">
    </div>
  </td>
</tr>
</tbody>
</table>
<script type="text/javascript">
(function(){
	/**
	 * 工厂方法, 创建$对象.
	 * @param {HTMLElement/String} selector 原生DOM对象或TAG选择器
	 * @return {$} $类型对象
	 */
	function $(selector) {
		if (this instanceof $) {
			if (selector.nodeType) {
				this[0] = selector;
				this.length = 1;
				return this;
			}
			var elems = document.getElementsByTagName(selector);
			this.setArray($.makeArray(elems));
		}
		else return new $(selector);
	}
	/**
	 * 将类数组对象转换成数组.
	 * @private
	 * @param {Mixed} 基本对象
	 * @return {Array} 数组
	 */
	$.makeArray = function (array) {
		var ret = [];
		if (array) {
			var i = array.length;
			if (array.split || array.setInterval || array.call) ret[0] = array;
			else while (i) ret[--i] = array[i];
		}
		return ret;
	}
	/**
	 * 事件模块
	 * @module
	 */
	$.event = {
		/**
		 * 修正事件对象使之标准化.
		 * @param {Event}
		 * @return {Event}
		 */
		fix: function (event) {
			var legacy = event;
			var event = {
				legacy: legacy
			};
			for (var prop in legacy)
				event[prop] = legacy[prop];
			if (event.pageX == null && event.clientX != null) {
				var doc = document.documentElement,
					body = document.body;
				event.pageX = event.clientX + Math.max(doc && doc.scrollLeft || 0, body && body.scrollLeft || 0) - (doc && doc.clientLeft || 0);
				event.pageY = event.clientY + Math.max(doc && doc.scrollTop || 0, body && body.scrollTop || 0) - (doc && doc.clientTop || 0);

			}
			return event;
		}
	}
	$.prototype = {
		/**
		 * 遍历匹配的DOM元素执行某个函数. 
		 * @param {Function} 回调函数. 作用域为DOM元素, 返回false中断迭代
		 * @param {Mixed} 附加参数
		 * @return {$}
		 */
		each: function (fn, args) {
			for (var i = 0, length = this.length; i < length; i++)
				if (fn.call(this[i], i, this, args) === false) break;
			return this;
		},
		/**
		 * 获取或设置匹配元素相对当前文档的坐标. 
		 * @param {Object} 包含left和top索引的坐标. 参数非空设置坐标, 否则获取坐标
		 * @return {Mixed} 参数非空返回$对象自身, 否则返回坐标{left: left, top: top}
		 */
		offset: function (coords) {
			if (coords) {
				return this.each(function (elem) {
					this.style.left = coords.left + "px";
					this.style.top = coords.top + "px";
				});
			}
			var left = 0,
				top = 0;
			var elem = this[0];
			if (elem) {
				while (elem.offsetParent) {
					left += elem.offsetLeft;
					top += elem.offsetTop;
					elem = elem.offsetParent;
				}
			}
			return {
				left: left,
				top: top
			};
		},
		
		setArray: function (elems) {
			this.length = 0;
			Array.prototype.push.apply(this, elems);
			return this;
		},
		/**
		 * 为匹配元素注册事件响应 
		 * @param {String} 事件类型
		 * @param {Function} 事件处理函数
		 * @return {$}
		 */
		on: function (type, fn) {
			return this.each(function (elem) {
				var handler = function (event) {
					event = arguments[0] = $.event.fix(event);
					return fn.apply(this, arguments);
				};
				if (this.addEventListener) {
					this.addEventListener(type, handler, false);
				} else if (this.attachEvent) {
					this.attachEvent("on" + type, handler);
				}
			});
		}
	};


	var MAX_DIST = 37;		// 眼珠允许移动的最大距离
	var EYE_RADIUS = 59;	// 眼睛宽度/2
	var PUPIL_RADIUS = 7;	// 眼珠宽度/2

	$(document).on('mousemove', function (e) {
		$('img').each(function () {
			var coords = $(this.parentNode).offset();

			var centralX = coords.left + EYE_RADIUS;
			var centralY = coords.top + EYE_RADIUS;

			var distX = e.pageX - centralX;
			var distY = e.pageY - centralY;
			var dist = Math.sqrt(Math.pow(distX, 2) + Math.pow(distY, 2));
			if (dist > MAX_DIST) {
				var scale = MAX_DIST / dist;
				distX *= scale;
				distY *= scale;
			}

			$(this).offset({
				left: (distX + EYE_RADIUS - PUPIL_RADIUS),
				top: (distY + EYE_RADIUS - PUPIL_RADIUS)
			});

		});

	});
})();
</script>
</body>
</html>